package com.time.hellotime.components.login;

import android.Manifest;
import android.app.Activity;
import android.content.BroadcastReceiver;
import android.content.Context;
import android.content.Intent;
import android.content.IntentFilter;
import android.os.Bundle;
import android.os.Handler;
import android.os.Message;
import android.support.annotation.NonNull;
import android.support.annotation.Nullable;
import android.support.v4.content.LocalBroadcastManager;
import android.text.TextUtils;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;

import com.google.gson.Gson;
import com.sina.weibo.sdk.auth.Oauth2AccessToken;
import com.sina.weibo.sdk.auth.WbAuthListener;
import com.sina.weibo.sdk.auth.WbConnectErrorMessage;
import com.sina.weibo.sdk.auth.sso.SsoHandler;
import com.tencent.connect.UserInfo;
import com.tencent.tauth.IUiListener;
import com.tencent.tauth.Tencent;
import com.tencent.tauth.UiError;
import com.time.hellotime.R;
import com.time.hellotime.app.AddressManager;
import com.time.hellotime.app.AppConfig;
import com.time.hellotime.app.WXManager;
import com.time.hellotime.base.BaseActivity;
import com.time.hellotime.components.MainActivity;
import com.time.hellotime.servermodel.BasicBean;
import com.time.hellotime.servermodel.User;
import com.time.hellotime.utils.JpushUtils;
import com.time.hellotime.utils.NetWorkUtils;
import com.time.hellotime.utils.ToastUtils;
import com.time.hellotime.views.CodeView;
import com.time.hellotime.views.TelephoneView;
import com.time.hellotime.webserver.helper.WebServerManager;
import com.time.hellotime.webserver.request.BasicRequest;
import com.time.hellotime.webserver.request.requestsParamters.LoginParameters;
import com.yanzhenjie.nohttp.Logger;
import com.yanzhenjie.nohttp.NoHttp;
import com.yanzhenjie.nohttp.RequestMethod;
import com.yanzhenjie.nohttp.rest.OnResponseListener;
import com.yanzhenjie.nohttp.rest.Request;
import com.yanzhenjie.nohttp.rest.RequestQueue;
import com.yanzhenjie.nohttp.rest.Response;
import com.yanzhenjie.permission.AndPermission;
import com.yanzhenjie.permission.PermissionListener;
import com.yanzhenjie.permission.Rationale;
import com.yanzhenjie.permission.RationaleListener;

import org.json.JSONException;
import org.json.JSONObject;

import java.lang.ref.WeakReference;
import java.util.List;

/**
 * Login - user
 * Created by Bing on 2017/10/25.
 * E-mail is tx16bing@163.com
 */

public class LoginActivity extends BaseActivity implements View.OnClickListener {

    private static final int REGISTER_REQUEST_CODE = 102;
    private static final int BINDING_REQUEST_CODE = 103;
    private static final int BASIC_PERMISSION_REQUEST_CODE = 110;

    private TelephoneView telephoneView;
    private CodeView codeView;
    private Button btnLogin;
    private TextView tvRegister;

    private TextView tvQQ, tvWx, tvWb;

    private Request request;
    private static final int LOGIN_USER_WHAT = 22;
    private static final int WB_INFO_WHAT = 23;
    private static final int LOGIN_QQ_WHAT = 24;
    private static final int LOGIN_WB_WHAT = 25;
    private static final int LOGIN_WX_WHAT = 26;
    private static final int USER_INFO_WHAT = 27;


    private String threeInfo;
    /**
     * 新浪微博
     */
    private SsoHandler mSsoHandler;
    /**
     * 封装了 "access_token"，"expires_in"，"refresh_token"，并提供了他们的管理功能
     */
    private Oauth2AccessToken mAccessToken;
    // wb_openid
    private String WB_uid;

    /**
     * QQ
     */
    private Tencent mTencent;
    private UserInfo userInfo;
    //qq_openid
    private String QQ_uid;

    /**
     * wx openid
     */
    private String WX_uid;


    private LocalBroadcastManager lbm;

    public static void start(Activity activity) {
        Intent intent = new Intent(activity, LoginActivity.class);
        activity.startActivity(intent);
    }

    @Override
    protected void onCreate(@Nullable Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_login);
        assignViews();
        addListener();

        // wb
        mSsoHandler = new SsoHandler(LoginActivity.this);
        // qq
        mTencent = Tencent.createInstance(getString(R.string.qq_app_id),
                this.getApplicationContext());

        requestBasicPermission();

        registerWxReceiver();
    }

    private void assignViews() {
        telephoneView = findView(R.id.ll_telephone);
        codeView = findView(R.id.ll_code);
        btnLogin = findView(R.id.btn_login);
        tvRegister = findView(R.id.tv_register);
        tvQQ = findView(R.id.tv_login_qq);
        tvWx = findView(R.id.tv_login_wx);
        tvWb = findView(R.id.tv_login_wb);
    }

    private void addListener() {
        btnLogin.setOnClickListener(this);
        tvRegister.setOnClickListener(this);
        tvQQ.setOnClickListener(this);
        tvWx.setOnClickListener(this);
        tvWb.setOnClickListener(this);
    }

    @Override
    public void onClick(View v) {
        switch (v.getId()) {

            case R.id.btn_login:
                // TODO: 2017/10/27
                if (!checkForm()) return;
                loginRequest();
                break;

            case R.id.tv_register:
                RegisterActivity.start(this, REGISTER_REQUEST_CODE, getString(R.string.register_normal));
                break;

            case R.id.tv_login_qq:
                if (!mTencent.isSessionValid()) {
                    // 注销登录mTencent.logout(this);
                    mTencent.login(LoginActivity.this, "all", new SelfQQAuthListener());
                }
                break;

            case R.id.tv_login_wx:
                WXManager.instance().loginToWx();
                break;

            case R.id.tv_login_wb:
                mSsoHandler.authorize(new SelfWbAuthListener());
                break;

            default:
                break;
        }
    }

    private boolean checkForm() {
        boolean formIsValid = true;
        if (TextUtils.isEmpty(telephoneView.getAccount())) {
            ToastUtils.showShort(getString(R.string.please_input_telephone));
            formIsValid = false;
        } else if (TextUtils.isEmpty(codeView.getCode())) {
            ToastUtils.showShort(getString(R.string.please_input_code));
            formIsValid = false;
        }

        return formIsValid;
    }

    /**
     * 基本权限管理
     */
    private void requestBasicPermission() {
        AndPermission.with(this)
                .requestCode(BASIC_PERMISSION_REQUEST_CODE)
                .permission(Manifest.permission.READ_EXTERNAL_STORAGE,
                        Manifest.permission.READ_PHONE_STATE)
                .callback(listener)
                // rationale作用是：用户拒绝一次权限，再次申请时先征求用户同意，再打开授权对话框；
                // 这样避免用户勾选不再提示，导致以后无法申请权限。
                // 你也可以不设置。
                .rationale(new RationaleListener() {
                    @Override
                    public void showRequestPermissionRationale(int requestCode, Rationale rationale) {
                        // 这里的对话框可以自定义，只要调用rationale.resume()就可以继续申请。
                        AndPermission.rationaleDialog(LoginActivity.this, rationale)
                                .show();
                    }
                })
                .start();
    }

    // 权限回调监听
    private PermissionListener listener = new PermissionListener() {
        @Override
        public void onSucceed(int requestCode, @NonNull List<String> grantPermissions) {
            if (requestCode == BASIC_PERMISSION_REQUEST_CODE) {
                // 表示读写的权限申请通过
                // 创建根目录
                AppConfig.getInstance().initDir();
            }
        }

        @Override
        public void onFailed(int requestCode, @NonNull List<String> deniedPermissions) {
            if (requestCode == BASIC_PERMISSION_REQUEST_CODE) {
                // 即使是用户选择了不在询问还是会toast该提示语
//                ToastUtils.showShort("请开启内部存储的读写权限");

            }
            // 用户否勾选了不再提示并且拒绝了权限，那么提示用户到设置中授权
            // 登录界面不需要
//            if (AndPermission.hasAlwaysDeniedPermission(LoginActivity.this, deniedPermissions)) {
//                // 第一种：用默认的提示语。
//                AndPermission.defaultSettingDialog(LoginActivity.this, 404).show();
//
//            }
        }
    };

    /**
     * 普通登录
     */
    private void loginRequest() {
        if (NetWorkUtils.isNetAvailable(this)) {
            request = new BasicRequest(AddressManager.getInstance().getAddress());
            LoginParameters parameters = new LoginParameters();
            parameters.setCommand(getString(R.string.command_loginAppPersonNormal));
            parameters.setAccountName(telephoneView.getAccount());
            parameters.setCode(codeView.getCode());
            if (TextUtils.isEmpty(JpushUtils.getRegisterId(this))) {
                parameters.setJpushId(getString(R.string.zero));
            } else {
                parameters.setJpushId(JpushUtils.getRegisterId(this));
            }
            request.add(getString(R.string.command), parameters.getCommand());
            request.add(getString(R.string.platform), parameters.getPlatform());
            request.add(getString(R.string.data), new Gson().toJson(parameters));
            request.setCancelSign(toString());
            WebServerManager.getInstance().add(this, request, this, LOGIN_USER_WHAT,
                    true, true, true);
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    /**
     * 微信登录
     */
    private void loginWx(String info) {
        if (NetWorkUtils.isNetAvailable(this)) {
            request = new BasicRequest(AddressManager.getInstance().getAddress());
            LoginParameters parameters = new LoginParameters();
            parameters.setCommand(getString(R.string.command_loginAppPersonWeChat));
            parameters.setOpenId(WX_uid);
            parameters.setThirdPartyInfo(info);
            if (TextUtils.isEmpty(JpushUtils.getRegisterId(this))) {
                parameters.setJpushId(getString(R.string.zero));
            } else {
                parameters.setJpushId(JpushUtils.getRegisterId(this));
            }
            request.add(getString(R.string.command), parameters.getCommand());
            request.add(getString(R.string.platform), parameters.getPlatform());
            request.add(getString(R.string.data), new Gson().toJson(parameters));
            request.setCancelSign(toString());
            WebServerManager.getInstance().add(this, request, this, LOGIN_WX_WHAT,
                    true, true, true);
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    /**
     * 微博登录
     */
    private void loginWb(String info) {
        if (NetWorkUtils.isNetAvailable(this)) {
            request = new BasicRequest(AddressManager.getInstance().getAddress());
            LoginParameters parameters = new LoginParameters();
            parameters.setCommand(getString(R.string.command_loginAppPersonQQ));
            parameters.setOpenId(WB_uid);
            parameters.setThirdPartyInfo(info);
            if (TextUtils.isEmpty(JpushUtils.getRegisterId(this))) {
                parameters.setJpushId(getString(R.string.zero));
            } else {
                parameters.setJpushId(JpushUtils.getRegisterId(this));
            }
            request.add(getString(R.string.command), parameters.getCommand());
            request.add(getString(R.string.platform), parameters.getPlatform());
            request.add(getString(R.string.data), new Gson().toJson(parameters));
            request.setCancelSign(toString());
            WebServerManager.getInstance().add(this, request, this, LOGIN_WB_WHAT,
                    true, true, true);
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    /**
     * qq登录
     */
    private void loginQQ(String info) {
        if (NetWorkUtils.isNetAvailable(this)) {
            request = new BasicRequest(AddressManager.getInstance().getAddress());
            LoginParameters parameters = new LoginParameters();
            parameters.setCommand(getString(R.string.command_loginAppPersonQQ));
            parameters.setOpenId(QQ_uid);
            parameters.setThirdPartyInfo(info);
            if (TextUtils.isEmpty(JpushUtils.getRegisterId(this))) {
                parameters.setJpushId(getString(R.string.zero));
            } else {
                parameters.setJpushId(JpushUtils.getRegisterId(this));
            }
            request.add(getString(R.string.command), parameters.getCommand());
            request.add(getString(R.string.platform), parameters.getPlatform());
            request.add(getString(R.string.data), new Gson().toJson(parameters));
            request.setCancelSign(toString());
            WebServerManager.getInstance().add(this, request, this, LOGIN_QQ_WHAT,
                    true, true, true);
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    private class SelfWbAuthListener implements WbAuthListener {

        @Override
        public void onSuccess(final Oauth2AccessToken token) {
            runOnUiThread(new Runnable() {
                @Override
                public void run() {
                    Logger.i("Sina token " + token);
                    mAccessToken = token;
                    if (mAccessToken.isSessionValid()) {
                        ToastUtils.showShort("授权成功");
                        WB_uid = mAccessToken.getUid();
                        obtainWbInfo();
                    }
                }
            });
        }

        @Override
        public void cancel() {
            ToastUtils.showShort("微博授权取消");
        }

        @Override
        public void onFailure(WbConnectErrorMessage errorMessage) {
            ToastUtils.showLong(errorMessage.getErrorMessage());
        }

    }

    private class SelfQQAuthListener implements IUiListener {

        @Override
        public void onComplete(Object o) {
            ToastUtils.showShort("授权成功");
            try {
                JSONObject jsonObject = new JSONObject(o.toString());
                initQQ(jsonObject);
                updateUserInfo();
            } catch (JSONException e) {
                e.printStackTrace();
            }
        }

        @Override
        public void onError(UiError e) {
            Logger.e("Error code : " + e.errorCode + ", msg : " + e.errorMessage + ", detail : " + e.errorDetail);
        }

        @Override
        public void onCancel() {
            Logger.i("授权取消");
        }
    }

    /**
     * 获取微博个人资料
     */
    private void obtainWbInfo() {
        if (NetWorkUtils.isNetAvailable(this)) {
            Request<String> request = NoHttp.createStringRequest("https://api.weibo.com/2/users/show.json", RequestMethod.GET);
            request.add("access_token", mAccessToken.getToken());
            request.add("uid", mAccessToken.getUid());
            request.setCancelSign(toString());
            RequestQueue queue = NoHttp.newRequestQueue();
            queue.add(WB_INFO_WHAT, request, new OnResponseListener<String>() {

                @Override
                public void onStart(int what) {

                }

                @Override
                public void onSucceed(int what, Response<String> response) {
                    String json = response.get();
                    Logger.i("WB info response " + json);
                    if (!TextUtils.isEmpty(json)) {
                        threeInfo = json;
                        if (!TextUtils.isEmpty(threeInfo)) {
                            loginWb(threeInfo);
                        }
                    }
                }

                @Override
                public void onFailed(int what, Response<String> response) {
                    if (null != response) {
                        ToastUtils.showLong(response.getException().getMessage());
                    }
                }

                @Override
                public void onFinish(int what) {

                }
            });
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    private void initQQ(JSONObject jsonObject) {
        try {
            String token = jsonObject.getString("access_token");
            String expires = jsonObject.getString("expires_in");
            String openId = jsonObject.getString("openid");
            if (!TextUtils.isEmpty(token) && !TextUtils.isEmpty(expires)
                    && !TextUtils.isEmpty(openId)) {
                mTencent.setAccessToken(token, expires);
                mTencent.setOpenId(openId);
                QQ_uid = openId;
            }
        } catch (Exception e) {
        }
    }

    private MyHandler mHandler = new MyHandler(this);

    private static class MyHandler extends Handler {

        private final WeakReference<LoginActivity> mActivity;

        private MyHandler(LoginActivity loginActivity) {
            this.mActivity = new WeakReference<>(loginActivity);
        }

        @Override
        public void handleMessage(Message msg) {
            LoginActivity mInstance = mActivity.get();
            if (mInstance == null){
                return;
            }
            if (msg.what == 0) {
                mInstance.handleWhat(msg);

            }
            super.handleMessage(msg);
        }

    }

    private void handleWhat(Message msg) {
        // Msg obj is upload server parameters
        threeInfo = msg.obj.toString();
        if (!TextUtils.isEmpty(threeInfo)) {
            loginQQ(threeInfo);
        }
    }

    private void updateUserInfo() {
        if (mTencent != null && mTencent.isSessionValid()) {
            IUiListener listener = new IUiListener() {
                @Override
                public void onError(UiError e) {
                }

                @Override
                public void onComplete(final Object response) {
                    Message msg = new Message();
                    msg.obj = response;
                    msg.what = 0;
                    mHandler.sendMessage(msg);
                }

                @Override
                public void onCancel() {
                    Logger.d("登录取消");
                }
            };
            userInfo = new UserInfo(this, mTencent.getQQToken());
            userInfo.getUserInfo(listener);
        }
    }

    // 加载个人信息
    private void getUserInfo() {
        if (NetWorkUtils.isNetAvailable(this)) {
            request = new BasicRequest(AddressManager.getInstance().getAddress());
            LoginParameters parameters = new LoginParameters();
            parameters.setCommand(getString(R.string.command_getUserInfo));
            parameters.setUserId(application.getAccount());
            if (TextUtils.isEmpty(JpushUtils.getRegisterId(this))) {
                parameters.setJpushId(getString(R.string.zero));
            } else {
                parameters.setJpushId(JpushUtils.getRegisterId(this));
            }
            request.add(getString(R.string.command), parameters.getCommand());
            request.add(getString(R.string.platform), parameters.getPlatform());
            request.add(getString(R.string.data), new Gson().toJson(parameters));
            request.setCancelSign(toString());
            WebServerManager.getInstance().add(this, request, this, USER_INFO_WHAT,
                    true, true, true);
        } else {
            ToastUtils.showShort(getString(R.string.network_error));
        }
    }

    @Override
    public void onSucceed(int what, Response<BasicBean> response) {

        BasicBean basicBean = response.get();
        if (basicBean == null) return;

        if (basicBean.isSuccess()) {
            if (what == LOGIN_USER_WHAT) {
                User user = basicBean.parseData(User.class);
                if (user == null) return;
                application.setAppInfo(user.getUserId(), telephoneView.getAccount(), true);
                getUserInfo();
            } else if (what == LOGIN_QQ_WHAT || what == LOGIN_WB_WHAT || what == LOGIN_WX_WHAT) {
                User user = basicBean.parseData(User.class);
                if (user == null) return;
                if (TextUtils.equals(getString(R.string.login_state_binded), user.getLoginType())) {
                    // 已经绑定
                    application.setAppInfo(user.getUserId(), telephoneView.getAccount(), true);
                    getUserInfo();
                } else {
                    if (what == LOGIN_QQ_WHAT) {
                        RegisterActivity.start(this,
                                REGISTER_REQUEST_CODE,
                                getString(R.string.register_QQ),
                                getString(R.string.register_QQ),
                                QQ_uid,
                                threeInfo);
                    } else if (what == LOGIN_WB_WHAT) {
                        RegisterActivity.start(this,
                                REGISTER_REQUEST_CODE,
                                getString(R.string.register_weibo),
                                getString(R.string.register_weibo),
                                WB_uid,
                                threeInfo);
                    } else {
                        RegisterActivity.start(this,
                                REGISTER_REQUEST_CODE,
                                getString(R.string.register_weChat),
                                getString(R.string.register_weChat),
                                WX_uid,
                                threeInfo);
                    }
                }
            } else if (what == USER_INFO_WHAT) {
                User user = basicBean.parseData(User.class);
                mVMcreator.setUserViewModel(user);
                if (user == null) return;
                MainActivity.start(this);
                finish();
            }
        } else {
            ToastUtils.showShort(basicBean.getMsg());
        }
    }


    @Override
    protected void onActivityResult(int requestCode, int resultCode, Intent data) {

        // Wb login
        if (null != mSsoHandler) {
            mSsoHandler.authorizeCallBack(requestCode, resultCode, data);
        }

        // QQ login
        Tencent.onActivityResultData(requestCode, resultCode, data, new SelfQQAuthListener());

        switch (requestCode) {

            case REGISTER_REQUEST_CODE:
                if (resultCode == RESULT_OK)
                    finish();
                break;

            case BINDING_REQUEST_CODE:
                if (resultCode == RESULT_OK)
                    finish();
                break;

            default:
                break;

        }

        super.onActivityResult(requestCode, resultCode, data);
    }

    private WxLoginReceiver wxReceiver;
    private class WxLoginReceiver extends BroadcastReceiver {

        @Override
        public void onReceive(Context context, Intent intent) {
            Logger.i("onReceive user info " + threeInfo);
            if (null != intent) {
                WX_uid = intent.getStringExtra("openId");
                threeInfo = intent.getStringExtra("wxUserInfo");
                if (!TextUtils.isEmpty(threeInfo)) {
                    loginWx(threeInfo);
                }
            }
        }
    }

    private void registerWxReceiver() {
        lbm = LocalBroadcastManager.getInstance(this);
        wxReceiver = new WxLoginReceiver();
        IntentFilter filter = new IntentFilter();
        filter.addAction("wx_login");
        lbm.registerReceiver(wxReceiver, filter);
    }

    @Override
    protected void onDestroy() {
        super.onDestroy();
        if (null != lbm){
            lbm.unregisterReceiver(wxReceiver);
        }
        if (null != telephoneView){
            telephoneView.removeCallback();
        }

        if (null != mHandler){
            mHandler.removeCallbacksAndMessages(null);
        }
    }
}
